using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Acms.DataControls
{
    [ToolboxData("<{0}:AcmsSiteMapDataSource runat=server></{0}:AcmsSiteMapDataSource>")]
    public class AcmsSiteMapDataSource : HierarchicalDataSourceControl
    {
        private string menuName;
        public string MenuName
        {
            get { return menuName; }
            set { menuName = value; }
        }

        private string rootText;
        public string RootText
        {
            get { return rootText; }
            set { rootText = value;}
        }

        private int parentId;
        public int ParentId
        {
            get { return parentId; }
        }

        private bool includeParent;
        public bool IncludeParent
        {
            get { return includeParent; }
        }

        private int siteId;
        public int SiteId
        {
            get { return siteId; }
            set { siteId = value; }
        }

        private int menuId;
        public int MenuId
        {
            get { return menuId; }
        }

        private void EnsureLoaded()
        {
            if (menuId == 0 && !string.IsNullOrEmpty(MenuName))
            {
                Bll.Menu menu = Bll.Menu.GetByNameAndSiteId(MenuName, SiteId);
                if (menu != null)
                {
                    menuId = menu.Id;
                    parentId = menu.ParentId;
                    includeParent = menu.IncludeParent;
                }
            }
        }

        private HierarchicalDataSourceView view;
        protected override HierarchicalDataSourceView GetHierarchicalView(string viewPath)
        {
            if (view == null)
            {
                EnsureLoaded();
                view = new AcmsSiteMapDataSourceView(this);
            }
            return view;
        }

        internal List<Bll.Post> GetInitial(bool ignoreRootText)
        {
            if (!ignoreRootText && !string.IsNullOrEmpty(RootText))
            {
                Bll.Post tmp = Bll.Post.CreateInstance();
                tmp.DisplayName = RootText;
                return GetList(tmp);
            }
            else if (MenuId != 0)
            {
                if (IncludeParent && ParentId != 0)
                {
                    Bll.Post tmp = Bll.Post.GetById(ParentId);
                    return GetList(tmp);
                }
                else if (ParentId != 0)
                {
                    return Bll.Post.GetAllByMenuIdAndParentId(MenuId, ParentId);
                }
                else
                {
                    return GetList(Bll.Post.GetTopLevelBySiteIdAndMenuId(SiteId, MenuId));
                }
            }
            else
            {
                return GetList(Bll.Post.GetTopLevelBySiteId(SiteId));
            }
        }

        internal List<Bll.Post> GetChildren(Bll.Post post)
        {
            if (post == null || post.Id == 0)
            {
                return GetInitial(true);
            }
            else if (MenuId != 0)
            {
                return Bll.Post.GetAllByMenuIdAndParentId(MenuId, post.Id);
            }
            else
            {
                return Bll.Post.GetAllByParentId(post.Id);
            }
        }

        private List<Bll.Post> GetList(Bll.Post post)
        {
            List<Bll.Post> tmp = new List<Acms.Bll.Post>();
            if(post != null)
                tmp.Add(post);
            return tmp;
        }

        protected override object SaveViewState()
        {
            ViewState["SiteId"] = siteId;
            ViewState["MenuName"] = menuName;
            ViewState["MenuId"] = menuId;
            ViewState["ParentId"] = parentId;
            ViewState["RootText"] = rootText;
            return base.SaveViewState();
        }

        protected override void LoadViewState(object savedState)
        {
            base.LoadViewState(savedState);
            if (ViewState["SiteId"] is int)
                siteId = (int)ViewState["SiteId"];
            menuName = ViewState["MenuName"] as string;
            if (ViewState["MenuId"] is int)
                menuId = (int)ViewState["MenuId"];
            if (ViewState["ParentId"] is int)
                parentId = (int)ViewState["ParentId"];
            rootText = ViewState["RootText"] as string;
        }
    }

    public class AcmsSiteMapDataSourceView : HierarchicalDataSourceView
    {
        public AcmsSiteMapDataSourceView(AcmsSiteMapDataSource owner) : base() { this.owner = owner; }

        AcmsSiteMapDataSource owner;

        public override IHierarchicalEnumerable Select()
        {
            return new AcmsSiteMapEnumerator(owner.GetInitial(false), owner);
        }
    }

    public class AcmsSiteMapEnumerator : IHierarchicalEnumerable
    {
        public AcmsSiteMapEnumerator(Bll.Post post, AcmsSiteMapDataSource owner)
        {
            this.posts = new List<Acms.Bll.Post>();
            posts.Add(post);
            this.owner = owner;
        }

        public AcmsSiteMapEnumerator(List<Bll.Post> posts, AcmsSiteMapDataSource owner)
        {
            this.posts = posts;
            this.owner = owner;
        }

        AcmsSiteMapDataSource owner;
        #region IHierarchicalEnumerable Members

        public IHierarchyData GetHierarchyData(object enumeratedItem)
        {
            return new AcmsSiteMapData(enumeratedItem as Bll.Post, owner);
        }

        #endregion

        #region IEnumerable Members

        private List<Bll.Post> posts = null;

        public System.Collections.IEnumerator GetEnumerator()
        {
            if (posts != null)
            {
                foreach (Bll.Post p in posts)
                {
                    yield return p;
                }
            }
        }

        #endregion
    }

    public class AcmsSiteMapData : IHierarchyData
    {
        public AcmsSiteMapData(Bll.Post post, AcmsSiteMapDataSource owner)
        {
            this.post = post;
            this.owner = owner;
        }

        AcmsSiteMapDataSource owner;

        private Bll.Post post;

        private List<Bll.Post> children;
        protected List<Bll.Post> Children
        {
            get 
            {
                if (children == null)
                {
                    children = owner.GetChildren(post);
                }
                return children;
            }

        }

        #region IHierarchyData Members

        public IHierarchicalEnumerable GetChildren()
        {
           return new AcmsSiteMapEnumerator(Children, owner);
        }

        public IHierarchyData GetParent()
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public bool HasChildren
        {
            get { return Children != null && Children.Count > 0; }
        }

        public object Item
        {
            get 
            {
                return post;
            }
        }

        public string Path
        {
            get
            {
                if (post != null)
                {
                    return post.Path;
                }
                else
                {
                    return null;
                }
            }
        }

        public string Type
        {
            get
            {
                if (post != null)
                {
                    return post.GetType().ToString();
                }
                else
                {
                    return null;
                }
            }
        }

        #endregion
    }
}
